/*
 * MainWindow.cpp
 * 
 *  Created on: Dec 28, 2010
 *  Author: Kevin Mueller
 */

#include "MainWindow.h"

#include "GaugePanel.h"
#include "PLLayout.h"
#include "SettingsWidget.h"
#include "AboutWidget.h"
#include "RouteWidget.h"
#include "SearchWidget.h"
#include "GPSWidget.h"
#include "MapWidget.h"

#include "IlluminateDisplay.h"

#include "../logic/Main.h"
#include "../logic/Clock.h"
#include "../logic/PositioningSystem.h"
#include "../logic/Settings.h"
#include "../logic/RoutingService.h"

#include <QtGui>

#include <QX11Info>
#include <X11/Xlib.h>
#include <X11/Xatom.h>

MainWindow::MainWindow(const QApplication& app, QWidget *parent = 0) :
	QMainWindow(parent) {
	setWindowTitle(tr("OpenNav"));

	subWidgetActivated = false;

	app.installTranslator(&qtTranslator);
	app.installTranslator(&appTranslator);

	connect(this, SIGNAL(retranslateRequest()), this, SLOT(retranslateUi()));

	illuminator = new IlluminateDisplay(this);
}

MainWindow::~MainWindow() {
	delete illuminator;
}

bool MainWindow::init() {
	qDebug() << "initializing GUI...";

	createActions();
	createComponents();
	createContextMenue();
	createButtons();

	createLandscape();
	createPortrait();
	createAutoLayout();

	selfAssignLayout();
	changedDisplayOrientationSetting();

	const Main& main = Main::getInstance();
	connect(main.getSettings().getOrientation(), SIGNAL(settingChanged(AbstractSetting*)), this, SLOT(
					changedDisplayOrientationSetting()));

	connect(&main.getRoutingService(), SIGNAL(startNavigation()), this, SLOT(startNavigation()));

	// set default or last set language
	switchLanguage();
	volumeKeysGrabber();

//	bStopNavigation->hide();

	qDebug() << "GUI successfully initialized";
	return true;
}

void MainWindow::createActions() {
	qDebug() << "Creating actions...";

	searchAction = new QAction(this);
	connect(searchAction, SIGNAL(triggered()), this, SLOT(showSearch()));

	preferencesAction = new QAction(this);
	connect(preferencesAction, SIGNAL(triggered()), this, SLOT(
			showPreferences()));

	poiAction = new QAction(this);
	connect(poiAction, SIGNAL(triggered()), this, SLOT(showPOI()));

	gpsAction = new QAction(this);
	connect(gpsAction, SIGNAL(triggered()), this, SLOT(showGPS()));

	routeAction = new QAction(this);
	connect(routeAction, SIGNAL(triggered()), Main::getInstance().getRouteSettings(), SLOT(reset()));
	connect(routeAction, SIGNAL(triggered()), this, SLOT(showRoute()));

	aboutAction = new QAction(this);
	connect(aboutAction, SIGNAL(triggered()), this, SLOT(showAbout()));

	qDebug() << "done!";
}

void MainWindow::createComponents() {
	qDebug() << "Creating components...";

	time = new TimeGauge();
	velocity = new VelocityGauge();
	arrival = new ArrivalGauge();
	distance = new DistanceGauge();
	compass = new Compass();
	curRoad = new CurrentRoad();
	map = new MapWidget(this);

	qDebug() << "done!";
}

void MainWindow::createButtons() {
	qDebug() << "Creating buttons...";

	bFullScreen = new QPushButton();
	bFullScreen->setIcon(QIcon(IMAGEDIR "/fullscreen.png"));
	connect(bFullScreen, SIGNAL(clicked()), this, SLOT(toggleFullScreen()));

	bPositioning = new QPushButton();
	bPositioning->setIcon(QIcon(IMAGEDIR "/positioning.png"));
	Main& map = Main::getInstance();
	connect(bPositioning, SIGNAL(clicked()), &map.getPositioningSystem(), SLOT(
			toggle()));

	bStopNavigation = new QPushButton();
	connect(bStopNavigation, SIGNAL(clicked()), this, SLOT(stopNavigation()));

	qDebug() << "done!";
}

void MainWindow::createContextMenue() {
	qDebug() << "Creating context menue...";

	QMenu *fileMenu = menuBar()->addMenu(tr("Options"));
	fileMenu->addAction(searchAction);
	fileMenu->addAction(routeAction);
	fileMenu->addAction(poiAction);
	fileMenu->addAction(gpsAction);
	fileMenu->addAction(preferencesAction);
	fileMenu->addAction(aboutAction);

	qDebug() << "done!";
}

void MainWindow::createLandscape() {
	qDebug() << "creating landscape layout";

	qDebug() << "-> Building gauges";
	QBoxLayout *gaugesContainer = new QVBoxLayout;
	QFormLayout *gauges = new QFormLayout;
	gauges->addRow(tr("T: "), time);
	gauges->addRow(tr("V: "), velocity);
	gauges->addRow(tr("A: "), arrival);
	gauges->addRow(tr("D: "), distance);
	gauges->addRow(curRoad);
	gaugesContainer->addLayout(gauges);

	QBoxLayout *compassLayout = new QVBoxLayout;
	compassLayout->addWidget(compass);
	compassLayout->setAlignment(Qt::AlignCenter);
	gaugesContainer->addLayout(compassLayout);
	qDebug() << "-> done!";

	qDebug() << "-> Building buttons";
	QBoxLayout *buttonsLayout = new QHBoxLayout;
	buttonsLayout->addWidget(bPositioning);
	buttonsLayout->addWidget(bFullScreen);
	qDebug() << "-> done!";

	QBoxLayout *controlsLayout = new QVBoxLayout;
	controlsLayout->addLayout(gaugesContainer);
	controlsLayout->addStretch();
	controlsLayout->addWidget(bStopNavigation);
	controlsLayout->addLayout(buttonsLayout);

	landscapeLayout = new QHBoxLayout();
	landscapeLayout->addWidget(map, 10);
	landscapeLayout->addLayout(controlsLayout, 2);

	qDebug() << "done!";
}

void MainWindow::createPortrait() {
	qDebug() << "creating portrait layout";

	qDebug() << "-> Building gauges";

	QBoxLayout *gaugesContainer = new QHBoxLayout;
//	QFormLayout *gauges = new QFormLayout;
//	gauges->addRow(tr("T: "), time);
//	gauges->addRow(tr("V: "), velocity);
//	gauges->addRow(tr("A: "), arrival);
//	gauges->addRow(tr("D: "), distance);
	gaugesContainer->setSpacing(5);
	gaugesContainer->addWidget(time);
	gaugesContainer->addWidget(velocity);
	gaugesContainer->addWidget(arrival);
	gaugesContainer->addWidget(distance);

	QBoxLayout *headerLine = new QHBoxLayout;
	headerLine->addLayout(gaugesContainer);
	headerLine->addWidget(compass);
	qDebug() << "-> done!";

	qDebug() << "-> Building buttons";
	QHBoxLayout *tmpLayout = new QHBoxLayout;
	tmpLayout->addWidget(bStopNavigation);
	tmpLayout->addWidget(bPositioning);
	tmpLayout->addWidget(bFullScreen);
	qDebug() << "-> done!";

	portraitLayout = new QVBoxLayout();
	portraitLayout->addLayout(headerLine, 1);
	portraitLayout->addWidget(map, 10);
	portraitLayout->addLayout(tmpLayout, 1);

	qDebug() << "done!";
}

void MainWindow::createAutoLayout() {
	qDebug() << "creating auto layout";

	autoLayout = new PLLayout();
	autoLayout->setPLayout(portraitLayout);
	autoLayout->setLLayout(landscapeLayout);

	qDebug() << "done!";
}

void MainWindow::selfAssignLayout() {
	qDebug() << "set layout as central widget";

	mainWidget = new QWidget();
	mainWidget->setLayout(autoLayout);
	this->setCentralWidget(mainWidget);

	qDebug() << "done!";
}

void MainWindow::startNavigation(){
	bStopNavigation->show();
	map->rerender();
}

void MainWindow::stopNavigation(){
	QMessageBox::StandardButton reply;
	reply = QMessageBox::question(this, tr("Stop Navigation?"),
				tr("Would you really like to stop the navigation and remove the calculated route?"),
				QMessageBox::Yes | QMessageBox::No);
	if (reply == QMessageBox::Yes){
		Main::getInstance().getRoutingService().stop();
			bStopNavigation->hide();
			map->rerender();
	}
}

void MainWindow::showGPS() {
	subWidgetActivated = true;
	GPSWidget gps(this);
	gps.resize(gps.sizeHint());
	gps.exec();
	subWidgetActivated = false;
}

void MainWindow::showPOI() {
	qDebug() << "show POI";
}

void MainWindow::showRoute() {
	subWidgetActivated = true;
	RouteWidget route(this);
	route.exec();
	subWidgetActivated = false;
}

void MainWindow::showSearch() {
	subWidgetActivated = true;
	SearchWidget search(this);
	connect(&search, SIGNAL(centeringMap(const LabeledCoordinate&)), map, SLOT(setCenter(const LabeledCoordinate&)));
	search.resize(search.sizeHint());
	search.exec();
	subWidgetActivated = false;
}

void MainWindow::showPreferences() {
	subWidgetActivated = true;
	SettingsWidget settings(this);
	settings.resize(settings.sizeHint());
	settings.exec();
	subWidgetActivated = false;
}

void MainWindow::showAbout() {
	subWidgetActivated = true;
	AboutWidget about(this);
	about.resize(about.sizeHint());
	about.exec();
	subWidgetActivated = false;
}

bool MainWindow::isFullScreen() const{
	return windowState() & Qt::WindowFullScreen;
}

void MainWindow::toggleFullScreen() {
	isFullScreen() ? showNormal() : showFullScreen();
}

void MainWindow::switchLanguage() {
	QString locale = Language::getLocale(
			static_cast<Language*> (Main::getInstance().getSettings().getLanguage())
		);
	qtTranslator.load("qt_" + locale, QLibraryInfo::location(
			QLibraryInfo::TranslationsPath));
	appTranslator.load("opennav_" + locale, TRANSLATIONDIR);

	emit retranslateRequest();
}

void MainWindow::changedDisplayOrientationSetting() {
	AbstractSetting* s = Main::getInstance().getSettings().getOrientation();
	switch (s->getCurrent()) {
	case DisplayOrientation::AUTOMATIC: {
#ifdef Q_WS_MAEMO_5
		setAttribute(Qt::WA_Maemo5AutoOrientation, true);
		setAttribute(Qt::WA_Maemo5LandscapeOrientation, false);
		setAttribute(Qt::WA_Maemo5PortraitOrientation, false);
#endif
		resize( sizeHint());
		autoLayout->setAutoRotate(true);
		break;
	}
	case DisplayOrientation::LANDSCAPE: {
#ifdef Q_WS_MAEMO_5
		setAttribute(Qt::WA_Maemo5AutoOrientation, false);
		setAttribute(Qt::WA_Maemo5LandscapeOrientation, true);
		setAttribute(Qt::WA_Maemo5PortraitOrientation, false);
#endif
		autoLayout->activateLLayout();
		autoLayout->setAutoRotate(false);
		break;
	}
	case DisplayOrientation::PORTRAIT: {
#ifdef Q_WS_MAEMO_5
		setAttribute(Qt::WA_Maemo5AutoOrientation, false);
		setAttribute(Qt::WA_Maemo5LandscapeOrientation, false);
		setAttribute(Qt::WA_Maemo5PortraitOrientation, true);
#endif
		autoLayout->activatePLayout();
		autoLayout->setAutoRotate(false);
		break;
	}
	}
}

void MainWindow::retranslateUi() {
	searchAction->setText(tr("&Search"));
	searchAction->setStatusTip(tr("Looking for Cities, Streets, ..."));

	preferencesAction->setText(tr("&Preferences"));
	preferencesAction->setStatusTip(tr("Change application settings."));

	poiAction->setText(tr("POI"));
	poiAction->setStatusTip(tr("Opens the points of interest interface"));

	gpsAction->setText(tr("&GPS-Information"));
	gpsAction->setStatusTip(tr(
			"Prints information about the current GPS status"));

	routeAction->setText(tr("&Route"));
	routeAction->setStatusTip(tr("Opens route calculation"));

	aboutAction->setText(tr("&About"));
	aboutAction->setStatusTip(tr("Shows information about this application"));

	bStopNavigation->setText(tr("Stop Navigation"));
}

void MainWindow::volumeKeysGrabber() {
	AbstractSetting *s = Main::getInstance().getSettings().getVolumeKeys();
	unsigned long val = (s->getCurrent() == VolumeKeys::ZOOMING) ? 1 : 0;

	Atom atom = XInternAtom(QX11Info::display(), "_HILDON_ZOOM_KEY_ATOM", 0);
	XChangeProperty(QX11Info::display(), this->winId(), atom, XA_INTEGER, 32,
			PropModeReplace, (unsigned char *) &val, 1);
}

void MainWindow::keyPressEvent(QKeyEvent * event) {
	switch (event->key()) {
	case Qt::Key_F7: // F7 is keycode for increasing volume on the N900
		emit increaseKeyPressed();
		break;
	case Qt::Key_F8: // F8 is keycode for decreasing volume on the N900
		emit decreaseKeyPressed();
		break;
	}
}

void MainWindow::resizeEvent(QResizeEvent* event) {
	// Call the autoLayout convenience function for the event handling
	autoLayout->resizeEvent(event);
	// Call base class resize event handler
	QMainWindow::resizeEvent(event);
	event->accept();
	//             #ifdef Q_OS_SYMBIAN
	//                 showMaximized();
	//                 #endif
}

void MainWindow::hideEvent(QHideEvent *event) {
	qDebug() << "Hide event!" << event << event->type();
	QMainWindow::hideEvent(event);
	event->accept();
}

void MainWindow::showEvent(QShowEvent *event) {
	QMainWindow::showEvent(event);
	event->accept();
}

void MainWindow::enterEvent(QEvent * event) {
	Main::getInstance().normalMode();
	QMainWindow::enterEvent(event);
	event->accept();
}

void MainWindow::leaveEvent(QEvent * event) {
	// TODO: enable power save mode only when application is moved to the background and not when another app-dialog was opened
	Main::getInstance().powerSave();
	QMainWindow::leaveEvent(event);
	event->accept();
}

void MainWindow::closeEvent(QCloseEvent *event) {
	delete this;
	Main::getInstance().destruct();
	wait();
	qDebug() << "Bye!";
}
